package com.jason.mail;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.util.Date;
import java.util.Properties;


/**
 * 邮件发送器
 *
 * @Author xiangchaozhou
 */
public class MailSender {


    private static Logger logger = LoggerFactory.getLogger(MailSender.class);

    /**
     * 以文本格式发送邮件
     *
     * @param mailInfo 待发送的邮件的信息
     */
    public static boolean sendTextMail(MailSenderInfo mailInfo) {
        logger.info("sendTextMail start");
        // 判断是否需要身份认证
        SelfAuthenticator authenticator = null;
        Properties pro = mailInfo.getProperties();
        if (mailInfo.isValidate()) {
            // 如果需要身份认证，则创建一个密码验证器
            authenticator = new SelfAuthenticator(mailInfo.getUserName(), mailInfo.getPassword());
        }
        // 根据邮件会话属性和密码验证器构造一个发送邮件的session
        Session sendMailSession = Session.getDefaultInstance(pro, authenticator);
        logger.info("create  sendMailSession");
        try {
            // 根据session创建一个邮件消息
            Message mailMessage = new MimeMessage(sendMailSession);
            // 创建邮件发送者地址
            Address from = new InternetAddress(mailInfo.getFromAddress());
            // 设置邮件消息的发送者
            mailMessage.setFrom(from);
            // 创建邮件的接收者地址，并设置到邮件消息中
            mailMessage.setRecipients(Message.RecipientType.TO, buildReceiveAddresses(mailInfo.getToAddresses()));
            // 设置邮件消息的主题
            mailMessage.setSubject(mailInfo.getSubject());
            // 设置邮件消息发送的时间
            mailMessage.setSentDate(new Date());
            // 设置邮件消息的主要内容
            String mailContent = mailInfo.getContent();
            mailMessage.setText(mailContent);
            // 发送邮件
            Transport.send(mailMessage);
            logger.info("sendTextMail end");
            return true;
        } catch (MessagingException ex) {
            logger.error("sendTextMail error",ex);
            ex.printStackTrace();
        }
        return false;
    }


    /**
     * 发送邮件
     * 功能如下：
     * 1、可以携带附件
     * 2、支持HTML
     * 3、支持发送多人
     *
     * @param mailInfo 待发送的邮件的信息
     */
    public static boolean sendMail(MailSenderInfo mailInfo) {
        logger.info("sendMail start");
        // 判断是否需要身份认证
        SelfAuthenticator authenticator = null;
        Properties pro = mailInfo.getProperties();
        if (mailInfo.isValidate()) {
            // 如果需要身份认证，则创建一个密码验证器
            logger.info("create authenticator");
            authenticator = new SelfAuthenticator(mailInfo.getUserName(), mailInfo.getPassword());
        }
        // 根据邮件会话属性和密码验证器构造一个发送邮件的session
        Session sendMailSession = Session.getDefaultInstance(pro, authenticator);
        logger.info("create  sendMailSession");
        try {
            // 根据session创建一个邮件消息
            Message mailMessage = new MimeMessage(sendMailSession);
            // 创建邮件发送者地址
            Address from = new InternetAddress(mailInfo.getFromAddress());
            // 设置邮件消息的发送者
            mailMessage.setFrom(from);
            // 创建邮件的接收者地址，并设置到邮件消息中
            mailMessage.setRecipients(Message.RecipientType.TO, buildReceiveAddresses(mailInfo.getToAddresses()));
            // 创建邮件的抄送者地址
            if (null != mailInfo.getCcAddresses()) {
                mailMessage.setRecipients(Message.RecipientType.CC, buildReceiveAddresses(mailInfo.getCcAddresses()));
            }
            // 设置邮件消息的主题
            mailMessage.setSubject(mailInfo.getSubject());
            // 设置邮件消息发送的时间
            mailMessage.setSentDate(new Date());
            // 设置邮件消息的主要内容
            mailMessage.setContent(createContent(mailInfo.getContent(), mailInfo.getAttachFileNames()));
            // 发送邮件
            Transport.send(mailMessage);
            logger.info("sendMail end");
            return true;
        } catch (MessagingException ex) {
            logger.error("sendMail error",ex);
            ex.printStackTrace();
        }
        return false;
    }

    private static Address[] buildReceiveAddresses(String[] tos) {
        Address[] addresses = new Address[tos.length];
        for (int i = 0; i < tos.length; i++) {
            try {
                addresses[i] = new InternetAddress(tos[i]);
            } catch (AddressException e) {
                e.printStackTrace();
            }
        }
        return addresses;
    }

    /**
     * 根据传入的文件路径创建附件并返回
     */
    private static MimeBodyPart createAttachment(String fileName) throws Exception {
        MimeBodyPart attachmentPart = new MimeBodyPart();
        FileDataSource fds = new FileDataSource(fileName);
        attachmentPart.setDataHandler(new DataHandler(fds));
        attachmentPart.setFileName(MimeUtility.encodeText(fds.getName()));
        return attachmentPart;
    }

    /**
     * 根据传入的邮件正文body和文件路径创建图文并茂的正文部分
     * @throws MessagingException
     */
    /**
     * @param body
     * @param files
     * @return
     * @throws MessagingException
     */
    private static MimeMultipart createContent(String body, String[] files) throws MessagingException {
        // 用于保存最终正文部分
        // 用于组合文本和图片，"related"型的MimeMultipart对象
        MimeMultipart allPart = new MimeMultipart("mixed");
        // 正文的文本部分
        MimeBodyPart textBody = new MimeBodyPart();
        textBody.setContent(body, "text/html;charset=utf-8");
        allPart.addBodyPart(textBody);
        if (files != null && files.length > 0) {
            // 将邮件中各个部分组合到一个"mixed"型的 MimeMultipart 对象
            int index = 1;
            for (String fileName : files) {
                if (StringUtils.isNotBlank(fileName)) {
                    try {
                        MimeBodyPart bodyPart = createAttachment(fileName);
                        if (fileName.endsWith("jpg")) {
                            bodyPart.setContentID((index++) + "");

                        }
                        allPart.addBodyPart(bodyPart);
                    } catch (Exception e) {
                        logger.error("createContent error",e);
                        e.printStackTrace();
                    }
                }

            }
        }
        logger.info("createContent success");
        return allPart;
    }
}